<template>
  <el-row class="p-5 pt-0" @keyup.enter="getMenuData">

    <el-col v-if="showSearch">
      <el-form ref="searchForm" :inline="true" :model="search" class="demo-form-inline">
        <el-form-item label="菜单名称" class="font-black">
          <el-input v-model="search.menuName" :disabled="loading" :size="store.layoutSize" clearable
                    placeholder="请输入菜单名称"/>
        </el-form-item>
        <el-form-item label="状态" class="font-black">
          <el-select v-model="search.status" :disabled="loading" :size="store.layoutSize" clearable style="width: 100px"
                     placeholder="状态" @change="getMenuData">
            <el-option v-for="item in statusData.data" :label="item.dictLabel" :value="item.dictValue"/>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button :color="store.getTheme" :disabled="loading" :size="store.layoutSize" auto-insert-space
                     type="primary"
                     @click="getMenuData">
            <template #icon>
              <el-icon>
                <Search/>
              </el-icon>
            </template>
            查询
          </el-button>
          <el-button :color="store.getTheme" :disabled="loading" :size="store.layoutSize" auto-insert-space plain
                     @click="clearSearch">
            <template #icon>
              <el-icon>
                <Refresh/>
              </el-icon>
            </template>
            重置
          </el-button>
        </el-form-item>
      </el-form>
    </el-col>

    <el-col class="flex justify-between">
      <div>
        <el-button :color="store.getTheme" :disabled="loading" :size="store.layoutSize" auto-insert-space plain
                   type="primary"
                   @click="add">
          <template #icon>
            <el-icon>
              <Plus/>
            </el-icon>
          </template>
          新增
        </el-button>
        <el-button :disabled="loading" :size="store.layoutSize" auto-insert-space plain type="info" @click="expand">
          <template #icon>
            <el-icon>
              <Sort/>
            </el-icon>
          </template>
          展开/折叠
        </el-button>
      </div>
      <div>
        <el-tooltip
            class="box-item"
            effect="dark"
            :content="showSearch?'隐藏搜索':'显示搜索'"
            placement="top"
        >
          <el-button :color="store.getTheme" :size="store.layoutSize" @click="showSearch = !showSearch" circle>
            <el-icon>
              <Search/>
            </el-icon>
          </el-button>
        </el-tooltip>
        <el-tooltip
            class="box-item"
            effect="dark"
            content="刷新"
            placement="top"
        >
          <el-button :color="store.getTheme" :disabled="loading" :size="store.layoutSize" circle @click="getMenuData">
            <el-icon>
              <Refresh/>
            </el-icon>
          </el-button>
        </el-tooltip>
      </div>
    </el-col>

    <el-col class="mt-2">
      <el-table v-if="refreshTable" :size="store.layoutSize" v-loading="loading"
                element-loading-text="正在努力加载中..."
                :data="tableMenuData.data" ref="tableRef"
                style="width: 100%" table-layout="auto" row-key="menuId" :default-expand-all="expandAll"
                highlight-current-row empty-text="无数据" :tree-props="{children: 'children'}">

        <el-table-column label="菜单名称" width="180" prop="menuName"/>

        <el-table-column align="center" label="图标" width="70">
          <template #default="scope">
            <el-icon>
              <component v-if="scope.row.icon !== '#'" :is="scope.row.icon"/>
            </el-icon>
          </template>
        </el-table-column>

        <el-table-column align="center" label="排序" prop="orderNum" width="70"/>

        <el-table-column label="权限标识" width="250" prop="perms"/>

        <el-table-column label="组件路径" width="250" prop="component"/>

        <el-table-column align="center" label="状态">
          <template #default="scope">
            <el-tag :type="scope.row.status === '0' ? 'success' : 'danger'">{{
                scope.row.status === '0' ? '正常' : '停用'
              }}
            </el-tag>
          </template>
        </el-table-column>

        <el-table-column align="center" label="创建时间" width="180">
          <template #default="scope">
            {{ moment(scope.row.createTime).format('YYYY-MM-DD HH:mm:ss') }}
          </template>
        </el-table-column>

        <el-table-column align="center" label="操作">
          <template #default="scope">
            <el-link type="primary" :underline="false" class="text-xs" :style="{color: store.getTheme}"
                     :size="store.layoutSize"
                     @click="update(scope.row)">
              <el-icon>
                <EditPen/>
              </el-icon>
              修改
            </el-link>
            <el-link type="primary" :underline="false" class="text-xs ml-3" :style="{color: store.getTheme}"
                     :size="store.layoutSize" @click="addChild(scope.row)">
              <el-icon>
                <Plus/>
              </el-icon>
              新增
            </el-link>
            <el-link type="primary" :underline="false" class="text-xs ml-3" :style="{color: store.getTheme}"
                     :size="store.layoutSize" @click="del(scope.row)">
              <el-icon>
                <Delete/>
              </el-icon>
              删除
            </el-link>
          </template>
        </el-table-column>

      </el-table>
    </el-col>

    <!-- 添加或修改菜单对话框 -->
    <el-dialog :title="title" v-model="open" width="680px" append-to-body>
      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
        <el-row>
          <el-col :span="24">
            <el-form-item label="上级菜单" prop="parentId">
              <el-tree-select
                  style="width: 100%"
                  v-model="form.parentId"
                  :data="selectMenuData"
                  node-key="menuId"
                  :props="{label:'menuName'}"
                  highlight-current
                  check-strictly
                  :render-after-expand="false" placeholder="选择上级菜单"
              />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="菜单类型" prop="menuType">
              <el-radio-group v-model="form.menuType">
                <el-radio label="M">目录</el-radio>
                <el-radio label="C">菜单</el-radio>
                <el-radio label="F">按钮</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="24" v-if="form.menuType !== 'F'">
            <el-form-item label="菜单图标" prop="icon">
              <el-input v-model="form.icon" placeholder="请输入菜单图标"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="菜单名称" prop="menuName">
              <el-input v-model="form.menuName" placeholder="请输入菜单名称"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="显示排序" prop="orderNum">
              <el-input-number v-model="form.orderNum" controls-position="right" :min="0"/>
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="form.menuType != 'F'">
            <el-form-item prop="isFrame">
              <template #label>
                <el-tooltip content="选择是外链则路由地址需要以`http(s)://`开头" placement="top">
                  <el-icon>
                    <InfoFilled/>
                  </el-icon>
                </el-tooltip>
                是否外链
              </template>
              <el-radio-group v-model="form.isFrame">
                <el-radio label="0">是</el-radio>
                <el-radio label="1">否</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="form.menuType != 'F'">
            <el-form-item prop="path">
              <template #label>
                <el-tooltip content="访问的路由地址，如：`user`，如外网地址需内链访问则以`http(s)://`开头" placement="top">
                  <el-icon>
                    <InfoFilled/>
                  </el-icon>
                </el-tooltip>
                路由地址
              </template>
              <el-input v-model="form.path" placeholder="请输入路由地址"/>
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="form.menuType == 'C'">
            <el-form-item prop="component">
              <template #label>
                <el-tooltip content="访问的组件路径，如：`system/user/index`，默认在`views`目录下" placement="top">
                  <el-icon>
                    <InfoFilled/>
                  </el-icon>
                </el-tooltip>
                组件路径
              </template>
              <el-input v-model="form.component" placeholder="请输入组件路径"/>
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="form.menuType != 'M'">
            <el-form-item prop="perms">
              <el-input v-model="form.perms" placeholder="请输入权限标识" maxlength="100"/>
              <template #label>
                <el-tooltip content="控制器中定义的权限字符，如：@PreAuthorize(`@ss.hasPermi('system:user:list')`)"
                            placement="top">
                  <el-icon>
                    <InfoFilled/>
                  </el-icon>
                </el-tooltip>
                权限字符
              </template>
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="form.menuType == 'C'">
            <el-form-item prop="query">
              <el-input v-model="form.query" placeholder="请输入路由参数" maxlength="255"/>
              <template #label>
                <el-tooltip content='访问路由的默认传递参数，如：`{"id": 1, "name": "ry"}`' placement="top">
                  <el-icon>
                    <InfoFilled/>
                  </el-icon>
                </el-tooltip>
                路由参数
              </template>
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="form.menuType == 'C'">
            <el-form-item prop="isCache">
              <template #label>
                <el-tooltip content="选择是则会被`keep-alive`缓存，需要匹配组件的`name`和地址保持一致" placement="top">
                  <el-icon>
                    <InfoFilled/>
                  </el-icon>
                </el-tooltip>
                是否缓存
              </template>
              <el-radio-group v-model="form.isCache">
                <el-radio label="0">缓存</el-radio>
                <el-radio label="1">不缓存</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="form.menuType != 'F'">
            <el-form-item prop="visible">
              <template #label>
                <el-tooltip content="选择隐藏则路由将不会出现在侧边栏，但仍然可以访问" placement="top">
                  <el-icon>
                    <InfoFilled/>
                  </el-icon>
                </el-tooltip>
                显示状态
              </template>
              <el-radio-group v-model="form.visible">
                <el-radio v-for="item in showStatusData.data" :key="item.dictCode"
                          :label="item.dictValue">{{
                    item.dictLabel
                  }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12" v-if="form.menuType != 'F'">
            <el-form-item prop="status">
              <template #label>
                <el-tooltip content="选择停用则路由将不会出现在侧边栏，也不能被访问" placement="top">
                  <el-icon>
                    <InfoFilled/>
                  </el-icon>
                </el-tooltip>
                菜单状态
              </template>
              <el-radio-group v-model="form.status">
                <el-radio v-for="item in statusData.data" :key="item.dictCode"
                          :label="item.dictValue">{{
                    item.dictLabel
                  }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="flex justify-end">
        <el-button :loading="btnLoading" auto-insert-space type="primary" @click="submitForm(formRef)">确定</el-button>
        <el-button auto-insert-space @click="open = false">取消</el-button>
      </div>
    </el-dialog>
  </el-row>
</template>

<script setup lang="ts">
import moment from "moment";
import {useStore} from "@/store";
import {nextTick, reactive, ref} from "vue";
import {getDictData} from "@/api/dictData";
import {delMenu, getMenuDataByParams, saveMenu} from "@/api/menu";
import {ElMessageBox, ElNotification, FormInstance, FormRules} from "element-plus";

const store = useStore()

const open = ref(false)

const showSearch = ref(true)

const title = ref('')

const loading = ref(false)

const refreshTable = ref(true)

const formRef = ref<FormInstance>()

//展开树状图
const expandAll = ref(false)

function expand() {
  refreshTable.value = false
  expandAll.value = !expandAll.value
  nextTick(() => {
    refreshTable.value = true
  })
}

//下拉框菜单选择
const selectMenuData = reactive([{
  menuId: 0,
  menuName: '主类目',
  children: []
}])

//新增方法
function add() {
  clearForm()
  form.createBy = store.getUser.userName
  title.value = '添加菜单'
  selectMenuData[0].children = tableMenuData.data
  open.value = true
}

//赋值状态信息
const statusData = reactive({
  data: []
})
getDictData({'dictType': 'sys_normal_disable'}).then(result => {
  statusData.data = result.data.data
})

//赋值显示状态信息
const showStatusData = reactive({
  data: []
})
getDictData({'dictType': 'sys_show_hide'}).then(result => {
  showStatusData.data = result.data.data
})

//搜索表单
const search = reactive({
  menuName: null,
  status: null,
})

//清空表单
function clearSearch() {
  search.menuName = null
  search.status = null
  getMenuData()
}

//获取表格数据
const tableMenuData = reactive({
  data: []
})
getMenuData()

function getMenuData() {
  loading.value = true
  getMenuDataByParams(search).then(result => {
    tableMenuData.data = result.data.data
    loading.value = false
  })
}

//新增、修改表单
const form = reactive({
  menuId: null,
  parentId: 0,
  menuName: null,
  icon: null,
  menuType: "M",
  orderNum: null,
  isFrame: '1',
  isCache: '0',
  visible: '0',
  status: '0',
  path: null,
  component: null,
  perms: null,
  query: null,
  createBy: null,
  updateBy: null,
})

//清空表单
function clearForm() {
  form.menuId = null
  form.parentId = 0
  form.menuName = null
  form.icon = null
  form.menuType = "M"
  form.orderNum = null
  form.isFrame = '1'
  form.isCache = '0'
  form.visible = '0'
  form.status = '0'
  form.path = null
  form.component = null
  form.perms = null
  form.query = null
  form.createBy = null
  form.updateBy = null
}

//新增子级
function addChild(row) {
  clearForm()
  form.createBy = store.getUser.userName

  form.parentId = row.menuId
  selectMenuData[0].children = tableMenuData.data
  title.value = '添加菜单'
  open.value = true
}

//修改菜单
function update(row) {
  clearForm()
  form.updateBy = store.getUser.userName

  form.menuId = row.menuId
  form.parentId = row.parentId
  form.menuName = row.menuName
  form.icon = row.icon
  form.menuType = row.menuType
  form.orderNum = row.orderNum

  form.isFrame = row.isFrame.toString()
  form.visible = row.visible.toString()
  form.status = row.status
  form.isCache = row.isCache.toString()

  form.path = row.path
  form.component = row.component
  form.perms = row.perms
  form.query = row.query

  selectMenuData[0].children = tableMenuData.data
  title.value = '修改菜单'
  open.value = true
}

// 表单校验
const rules = reactive<FormRules>({
  menuName: [
    {required: true, message: "菜单名称不能为空", trigger: "blur"}
  ],
  orderNum: [
    {required: true, message: "菜单顺序不能为空", trigger: "blur"}
  ],
  path: [
    {required: true, message: "路由地址不能为空", trigger: "blur"}
  ],
  icon: [
    {required: true, message: "图标不能为空", trigger: "blur"}
  ],
})

const btnLoading = ref(false)

//提交新增、修改表单
const submitForm = async (formEl: FormInstance | undefined) => {
  if (!formEl) return
  await formEl.validate((valid) => {
    if (valid) {
      btnLoading.value = true
      saveMenu(form).then(result => {
        if (result.data.code === 200) {
          ElNotification({
            message: result.data.msg,
            type: 'success'
          })
          open.value = false
        }
        getMenuData()
        btnLoading.value = false
      })
    }
  })
}

//删除菜单
function del(val) {
  ElMessageBox.confirm('您确定要删除<' + val.menuName + '>菜单吗？', '警告', {
    confirmButtonText: '删除',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    loading.value = true
    delMenu(val.menuId).then(result => {
      if (result.data.code === 200) {
        ElNotification({
          message: result.data.msg,
          type: 'success'
        })
        getMenuData()
      }
      loading.value = false
    })
  })
}

</script>

<style scoped>

</style>
